﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;

namespace SearchAssembly
{
    /// <summary>
    /// Assembly helper class provides necessary functions to be used within the application.
    /// Assembly helper is a static class with public static methods.
    /// </summary>
    public static class AssemblyHelper
    {
        /// <summary>
        /// Returns the assemblies found within the provided path.
        /// This function searches for assemblies within nested folder structures.
        /// </summary>
        /// <param name="SelectedPath">Path where to search for assemblies</param>
        /// <returns>List of assemblies found within the provided path</returns>
        /// <remarks>
        /// This function returns only distinct assemblies to avoid duplicate names.
        /// </remarks>
        public static List<FileInfo> GetAssemblies(string SelectedPath)
        {
            DirectoryInfo selectedDirectory = new DirectoryInfo(SelectedPath);
            return selectedDirectory.GetFiles("*.dll", SearchOption.AllDirectories).Distinct ().ToList ();
        }

        /// <summary>
        /// Returns the references for the assembly
        /// </summary>
        /// <param name="AssemblyFileName">FileName of assembly for whom the references to be returned</param>
        /// <returns>References for the assembly</returns>
        public static CustomAssembly GetReferences(FileInfo AssemblyFileName)
        {
            CustomAssembly assemblyReferences = new CustomAssembly();
            Assembly currentAssembly = null;

            try
            {
                currentAssembly =  Assembly.LoadFrom(AssemblyFileName.FullName);
            }
            catch (Exception)
            {
                // Throw exception
            }
            
            assemblyReferences.Name = AssemblyFileName.Name;
            assemblyReferences.References = new List<string>();

            try
            {
                foreach (AssemblyName referencedAssemblyName in currentAssembly.GetReferencedAssemblies())
                {
                    assemblyReferences.References.Add(referencedAssemblyName.FullName);
                }
            }
            catch (NullReferenceException)
            {
                // ignore further assemblied and continue
            }            

            return assemblyReferences;
        }
    }

    /// <summary>
    /// Custom Assembly Structure that grouped information about an assembly
    /// </summary>
    public struct CustomAssembly
    {
        /// <summary>
        /// Name of the assembly
        /// </summary>
        public string Name;

        /// <summary>
        /// List of references for the assembly
        /// </summary>
        public List<string> References;
    };
}
